package com.zxy.supplier_system.server.service

import com.zxy.supplier_system.server.configuration.WechatProperties
import com.zxy.supplier_system.server.controller.GoodsController
import com.zxy.supplier_system.server.controller.MarketOrderController
import com.zxy.supplier_system.server.controller.MarketOrdersItemController
import com.zxy.supplier_system.server.controller.MarketsOrderController
import com.zxy.supplier_system.server.entity.*
import com.zxy.supplier_system.server.repository.*
import com.zxy.supplier_system.server.utils.*
import com.zxy.supplier_system.server.utils.wechat.official.SendTemplateMessageRequest
import com.zxy.supplier_system.server.utils.wechat.official.WechatOfficialAccountHelper
import com.zxy.supplier_system.server.utils.wechat.official.sendTemplateMessage
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import org.hibernate.Hibernate
import org.springframework.core.io.InputStreamResource
import org.springframework.data.domain.*
import org.springframework.data.jpa.domain.Specification
import org.springframework.data.repository.findByIdOrNull
import org.springframework.http.HttpStatus
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import org.springframework.web.server.ResponseStatusException
import java.time.OffsetDateTime
import java.util.*

@Service
class MarketOrderService(
    private val marketOrderRepository: MarketOrderRepository,
    private val marketRepository: MarketRepository,
    private val marketOrderItemRepository: MarketOrderItemRepository,
    private val employeeRepository: EmployeeRepository,
    private val systemServiceService: SystemServiceService,
    private val goodsRepository: GoodsRepository,
    private val notificationService: NotificationService,
    private val marketDeliveryOrderRepository: MarketDeliveryOrderRepository,
    private val employeeService: EmployeeService,
    private val employeeOperateRecordService: EmployeeOperateRecordService,
    private val goodsUnitRepository: GoodsUnitRepository,
    private val wechatOfficialAccountHelper: WechatOfficialAccountHelper,
    private val wechatProperties: WechatProperties,
) {

    private val orderNumberGenerator = OrderNumberGenerator(initialCurrentSequence = {
        marketOrderRepository.countToday()
    })

    @Transactional(readOnly = true)
    fun queryMarketOrder(
        queryMarketOrderRequest: MarketOrderController.QueryMarketOrderRequest,
        pageable: Pageable
    ): Page<MarketOrderController.QueryMarketOrderResponse> {

        val employee = employeeService.getRequiredCurrentEmployee()
        return this.marketOrderRepository.findAll(
            Specification.allOf(
                MarketOrderRepository.Specifications.marketIn(queryMarketOrderRequest.marketIds),
                MarketOrderRepository.Specifications.endDateLessThanOrEqualTo(queryMarketOrderRequest.endDate),
                MarketOrderRepository.Specifications.startDateGreaterThanOrEqualTo(queryMarketOrderRequest.startDate),
                MarketOrderRepository.Specifications.employeeIn(queryMarketOrderRequest.employeeIds),
                MarketOrderRepository.Specifications.statusEqual(queryMarketOrderRequest.status),
                MarketOrderRepository.Specifications.numberContains(queryMarketOrderRequest.number),
            ).and(
                if (employee.authorities.contains(Authority.卖场_订单_查询所有)) {
                    Specification.where(null)
                } else {
                    MarketOrderRepository.Specifications.marketSaleManagerEqual(employee.id!!)
                        .or(MarketOrderRepository.Specifications.marketShoppingGuidesContains(employee.id!!))
                }
            ), pageable
        ).map { marketOrder ->
            MarketOrderController.QueryMarketOrderResponse(
                marketOrder.id,
                marketOrder.employee.let {
                    IntIdAndName(it.id!!, it.name)
                },
                marketOrder.createdDateTime,
                marketOrder.lastModifiedDateTime,
                marketOrder.goodsList.size,
                marketOrder.market.let {
                    IntIdAndName(it.id, it.name)
                },
                marketOrder.status,
                marketOrder.number,
            )
        }
    }

    @Transactional
    fun createMarketOrder(marketId: Int): Int {
        val marketOrder = this.marketOrderRepository.save(MarketOrder().apply {
            this.market = marketRepository.findByIdOrNull(marketId).orElse404()
            this.number = orderNumberGenerator.generate()
        })
        this.employeeOperateRecordService.createMarketOrder(marketOrder)
        return marketOrder.id
    }

    @Transactional
    fun updateOrderGoods(
        id: Int,
        updateOrderGoodsRequest: MarketOrderController.UpdateOrderGoodsRequest
    ) {
        val marketOrder = this.marketOrderRepository.findByIdOrNull(id).orElse404()
        marketOrder.goodsList.clear()
        marketOrder.goodsList.addAll(
            updateOrderGoodsRequest.goodsList.mapIndexed { index, it ->
                MarketOrderItem().apply {
                    this.marketOrder = marketOrder
                    this.amount = it.amount
                    this.goods =
                        goodsRepository.findByIdAndSystemServiceAndDisableIsFalse(it.id, systemServiceService.getCurrentSystemService())
                            .orElse404()
                    this.sequence = index
                }
            }
        )
        this.marketOrderRepository.save(marketOrder)
    }

    @Transactional(readOnly = true)
    fun getMarketOrderDetail(id: Int, includeItems: Boolean): MarketOrderController.MarketOrderDetail {

        val marketOrder = this.marketOrderRepository.findByIdOrNull(id).orElse404()
        return MarketOrderController.MarketOrderDetail(
            marketOrder.id,
            marketOrder.createdDateTime,
            IntIdAndName(marketOrder.employee.id!!, marketOrder.employee.name),
            IntIdAndName(marketOrder.market.id, marketOrder.market.name),
            if (!includeItems) emptyList() else marketOrder.goodsList.map { item ->
                val goods = item.goods
                goods.let { it ->
                    MarketOrderController.MarketOrderItemResponse(
                        it.id,
                        it.name, it.barcode,
                        it.price,
                        it.amount,
                        it.createdDateTime,
                        it.lastModifiedDateTime,
                        it.brand?.toIntIdAndName(),
                        it.category?.toIntIdAndName(),
                        it.factory?.toIntIdAndName(),
                        item.amount,
                        it.boxSpecification,
                        item.unit?.toLongIdAndName(),
                        it.units.map {
                            QueryGoodsUnitResponse.formGoodsUnit(it)
                        },
                        it.registrationCertificateNumber,
                        it.recordFilingNumber,
                        it.expressionPeriod,
                        item.subGoods?.let(GoodsController.GoodsDetail.SubGoodsResponse::fromSubGoods),
                        item.note,
                    )
                }
            },
            marketOrder.submitDateTime,
            marketOrder.deliveryOrder?.createdDateTime,
            marketOrder.number,
        )
    }

    @Transactional
    fun addItem(orderId: Int, addMarketOrdersItemRequest: MarketOrdersItemController.AddMarketOrdersItemRequest) {
        val marketOrder = this.marketOrderRepository.findByIdOrNull(orderId).orElse404()
        if (marketOrder.goodsList.any { it.goods.id == addMarketOrdersItemRequest.goodsId && it.subGoods?.id == addMarketOrdersItemRequest.subGoodsId && it.marketOrder.id == orderId }) {
            throw ResponseStatusException(HttpStatus.BAD_REQUEST, "EXISTED")
        }
        marketOrder.goodsList.add(MarketOrderItem().apply {
            this.marketOrder = marketOrder
            this.goods = goodsRepository.findByIdAndSystemServiceAndDisableIsFalse(
                addMarketOrdersItemRequest.goodsId,
                systemServiceService.getCurrentSystemService()
            ).orElse404()
            this.subGoods =
                if (addMarketOrdersItemRequest.subGoodsId != null)
                    this.goods.subGoodsList.find { it.id == addMarketOrdersItemRequest.subGoodsId }.orElse404()
                else
                    null
            this.amount = addMarketOrdersItemRequest.amount
            this.sequence = marketOrder.goodsList.nextSequence
            this.note = addMarketOrdersItemRequest.note
            this.unit = addMarketOrdersItemRequest.unitId?.let {
                goodsUnitRepository.findByIdOrNull(it)
            }
        })
        this.marketOrderRepository.save(marketOrder)
        this.employeeOperateRecordService.addMarketOrderItem(marketOrder)
    }

    @Transactional
    fun deleteItem(orderId: Int, goodsId: Int) {
        val marketOrderItem = this.marketOrderItemRepository.findByMarketOrder_IdAndGoods_Id(orderId, goodsId)
        if (marketOrderItem != null) {
            this.marketOrderItemRepository.delete(marketOrderItem)
            this.employeeOperateRecordService.deleteMarketOrderItem(marketOrderItem)
        }
    }

    @Transactional
    fun deleteItem(orderId: Int, goodsId: Int, subGoodsId: Int) {
        val marketOrderItem =
            this.marketOrderItemRepository.findByMarketOrder_IdAndGoods_IdAndSubGoods_Id(orderId, goodsId, subGoodsId)
        if (marketOrderItem != null) {
            this.marketOrderItemRepository.delete(marketOrderItem)
            this.employeeOperateRecordService.deleteMarketOrderItem(marketOrderItem)
        }
    }

    @Transactional
    fun updateItemAmount(
        goodsId: Int,
        orderId: Int,
        updateItemAmountRequest: MarketOrdersItemController.UpdateItemAmountRequest
    ) {
        val marketOrderItem =
            this.marketOrderItemRepository.findByMarketOrder_IdAndGoods_Id(orderId, goodsId).orElse404()
        marketOrderItem.amount = updateItemAmountRequest.amount
        marketOrderItem.unit = updateItemAmountRequest.unitId?.let {
            this.goodsUnitRepository.findByIdOrNull(it)
        }
        this.marketOrderItemRepository.save(marketOrderItem)
        this.employeeOperateRecordService.updateMarketOrderItemAmount(marketOrderItem)
    }

    @Transactional
    fun updateItemAmount(
        goodsId: Int,
        orderId: Int,
        subGoodsId: Int,
        updateItemAmountRequest: MarketOrdersItemController.UpdateItemAmountRequest
    ) {
        val marketOrderItem =
            this.marketOrderItemRepository.findByMarketOrder_IdAndGoods_IdAndSubGoods_Id(orderId, goodsId, subGoodsId)
                .orElse404()
        marketOrderItem.amount = updateItemAmountRequest.amount
        marketOrderItem.unit = updateItemAmountRequest.unitId?.let {
            this.goodsUnitRepository.findByIdOrNull(it)
        }
        this.marketOrderItemRepository.save(marketOrderItem)
        this.employeeOperateRecordService.updateMarketOrderItemAmount(marketOrderItem)
    }

    fun getAllEmployees(): List<IntIdAndName> {
        return this.employeeRepository.findAll(
            EmployeeRepository.Specifications.haveMarketOrder().and(
                SystemServiceRepository.Specifications.systemServiceEquals(
                    { root -> root },
                    systemServiceService.getCurrentSystemService()
                )
            )
        ).map {
            IntIdAndName(it.id!!, it.name)
        }
    }

    @Transactional
    fun queryMarketOrderInMarket(
        marketId: Int,
        pageable: Pageable
    ): Slice<MarketsOrderController.QueryMarketOrderInMarketResponse> {
        return this.marketOrderRepository.findAllByMarket_Id(marketId, pageable).map {
            Hibernate.initialize(it.goodsList)
            MarketsOrderController.QueryMarketOrderInMarketResponse(
                it.id,
                it.employee.toIntIdAndName(),
                it.createdDateTime,
                it.goodsList.size,
                it.submitDateTime,
                it.status,
            )
        }
    }

    @Transactional(readOnly = true)
    fun queryOrderItemsInOrder(
        orderId: Int,
        pageable: Pageable
    ): Page<MarketOrdersItemController.OrderItemInOrderSummary> {
        return this.marketOrderItemRepository.findAllByMarketOrder_IdOrderBySequenceAsc(orderId, pageable).map {
            val goods = it.goods
            MarketOrdersItemController.OrderItemInOrderSummary.fromGoodsAndAmountAndUnit(
                goods,
                it.amount,
                it.unit,
                it.subGoods
            )
        }
    }

    fun exists(orderId: Int, goodsId: Int): Boolean {
        return this.marketOrderItemRepository.existsByMarketOrder_IdAndGoods_Id(orderId, goodsId)
    }

    fun exists(orderId: Int, barcode: String): Boolean {
        return this.marketOrderItemRepository.existsByMarketOrder_IdAndGoods_Barcode(orderId, barcode)
    }


    @Transactional
    fun addItem(orderId: Int, barcode: String): MarketOrdersItemController.OrderItemInOrderSummary {

        val currentSystemService = systemServiceService.getCurrentSystemService()
        val marketOrder = this.marketOrderRepository.findByIdAndMarket_SystemService(
            orderId,
            currentSystemService
        ).orElse404()
        if (marketOrder.goodsList.any { it.goods.barcode == barcode && it.subGoods == null && it.marketOrder.id == orderId }) {
            throw ResponseStatusException(HttpStatus.BAD_REQUEST, "EXISTED")
        }
        val goods =
            goodsRepository.findByBarcodeAndSystemServiceAndDisableIsFalse(barcode, currentSystemService)
                .orElse404()
        return orderItemInOrderSummary(marketOrder, goods)
    }

    @Transactional
    fun submitMarketOrder(id: Int) {
        val currentSystemService = systemServiceService.getCurrentSystemService()
        val marketOrder = this.marketOrderRepository.findByIdAndMarket_SystemService(
            id,
            currentSystemService
        ).orElse404()
        if (marketOrder.submitDateTime == null) {
            marketOrder.submitDateTime = OffsetDateTime.now()
            this.marketOrderRepository.save(marketOrder)
            this.employeeOperateRecordService.submitMarketOrder(marketOrder)
            fun pushNotificationToEmployee(employee: Employee){
                CoroutineScope(Dispatchers.IO).launch {
                    val wechatApiErrorResponse = employee.wechatUserInfo?.officialAccountOpenId?.let { openId ->
                        wechatOfficialAccountHelper.sendTemplateMessage(
                            openId,
                            wechatProperties.official.messageTemplates.waitAuditMarketOrder,
                            mapOf(
                                "thing14" to marketOrder.market.name,
                                "thing7" to marketOrder.employee.name,
                                "time4" to marketOrder.submitDateTime!!.format(DATE_MINUTE_FORMAT_CN),
                                "character_string2" to marketOrder.number
                            ),
                            miniprogram = SendTemplateMessageRequest.MiniprogramData(
                                wechatProperties.mini.appId, "pages/marketOrderDetail?id=${marketOrder.id}"
                            ),
                            clientMessageId = "submitMarketOrder${marketOrder.id}"
                        )
                    }
                    if (wechatApiErrorResponse?.errcode != 0) {

                    }
                }

                notificationService.pushNotification(Notification.Type.SUBMITTED_MARKET_ORDER, employee, OnlyIntId(id))

            }
            val notificationReceivers = mutableListOf<Employee>()
            marketOrder.market.saleManager?.let (notificationReceivers::add)
            employeeRepository.findAllBySetting_SubscribeAllMarketOrderSubmittedWechatNotificationIsTrueAndSystemService(currentSystemService).map(notificationReceivers::add)
            notificationReceivers.distinctBy { it.id }.forEach(::pushNotificationToEmployee)
        } else {
            throw ResponseStatusException(HttpStatus.BAD_REQUEST)
        }
    }

    @Transactional
    fun addItem(orderId: Int, goodsId: Int): MarketOrdersItemController.OrderItemInOrderSummary {
        val currentSystemService = systemServiceService.getCurrentSystemService()
        val marketOrder = this.marketOrderRepository.findByIdAndMarket_SystemService(
            orderId,
            currentSystemService
        ).orElse404()
        if (marketOrder.goodsList.any { it.goods.id == goodsId && it.subGoods == null && it.marketOrder.id == orderId })
            throw ResponseStatusException(HttpStatus.BAD_REQUEST, "EXISTED")
        val goods =
            goodsRepository.findByIdAndSystemServiceAndDisableIsFalse(goodsId, currentSystemService)
                .orElse404()
        return orderItemInOrderSummary(marketOrder, goods)
    }

    private fun orderItemInOrderSummary(
        marketOrder: MarketOrder,
        goods: Goods,
        subGoods: SubGoods? = null
    ): MarketOrdersItemController.OrderItemInOrderSummary {
        val latestItem =
            if (subGoods == null)
                this.marketOrderItemRepository.findFirstByMarketOrder_Market_IdAndGoods_IdOrderByMarketOrder_CreatedDateTimeDesc(
                    marketOrder.market.id,
                    goods.id
                )
            else
                this.marketOrderItemRepository.findFirstByMarketOrder_Market_IdAndGoods_IdAndSubGoods_IdOrderByMarketOrder_CreatedDateTimeDesc(
                    marketOrder.market.id,
                    goods.id,
                    subGoods.id!!
                )
        val amount = latestItem?.amount ?: 1
        val unit = latestItem?.unit
        val goodsUnit = unit ?: goods.basicUnit
        if (marketOrder.goodsList.any { it.goods.id == goods.id && it.subGoods?.id == subGoods?.id && it.marketOrder.id == marketOrder.id }) {
            throw ResponseStatusException(HttpStatus.BAD_REQUEST, "EXISTED")
        }
        marketOrder.goodsList.add(MarketOrderItem().apply {
            this.marketOrder = marketOrder
            this.goods =
                goods
            this.sequence = marketOrder.goodsList.nextSequence
            this.amount = amount
            this.unit = goodsUnit
            this.subGoods = subGoods
        })
        this.marketOrderRepository.save(marketOrder)
        this.employeeOperateRecordService.addMarketOrderItem(marketOrder)
        return MarketOrdersItemController.OrderItemInOrderSummary.fromGoodsAndAmountAndUnit(
            goods,
            amount,
            goodsUnit,
            subGoods,
        )
    }

    @Transactional
    fun delivery(id: Int): MarketDeliveryOrder {
        val marketOrder = this.marketOrderRepository.findByIdAndMarket_SystemService(
            id,
            systemServiceService.getCurrentSystemService()
        ).orElse404()
        if (marketOrder.submitDateTime == null) {
            throw ResponseStatusException(HttpStatus.BAD_REQUEST, "订单未提交")
        }
        var marketDeliveryOrder = marketDeliveryOrderRepository.save(MarketDeliveryOrder().apply {
            this.market = marketOrder.market
            this.order = marketOrder
            this.id = id
            this.number = marketOrder.number
        })
        marketOrder.employee.wechatUserInfo?.officialAccountOpenId?.let {
            this.wechatOfficialAccountHelper.sendTemplateMessage(
                it, wechatProperties.official.messageTemplates.auditedMarketOrder, mapOf(
                    "thing6" to marketOrder.market.name,
                    "time8" to marketDeliveryOrder.createdDateTime.format(DATE_MINUTE_FORMAT_CN),
                    "thing9" to marketOrder.employee.name,
                    "character_string1" to marketOrder.number
                ),
                url = "pages/marketOrderDetail?id=${marketOrder.id}",
                clientMessageId = "auditedMarketOrder${marketOrder.id}"
            )
        }
        marketOrderItemRepository.saveAll(marketOrder.goodsList)
        marketDeliveryOrder = marketDeliveryOrder.apply {
            this.goodsList = marketOrder.goodsList.map { marketOrderItem ->
                MarketDeliveryOrderItem().apply {
                    this.order = marketDeliveryOrder
                    this.amount = marketOrderItem.amount
                    this.goods = marketOrderItem.goods
                    this.unit = marketOrderItem.unit
                    this.subGoods = marketOrderItem.subGoods
                }
            }.toMutableList()
        }
        marketDeliveryOrder = this.marketDeliveryOrderRepository.save(marketDeliveryOrder)
        this.employeeOperateRecordService.deliveryMarketOrder(marketOrder)
        return marketDeliveryOrder
    }

    @Transactional
    fun delete(id: Int) {
        val employee = this.employeeService.getRequiredCurrentEmployee()
        val marketOrder = this.marketOrderRepository.findBy<MarketOrder, Optional<MarketOrder>>(
            Specification.allOf(MarketOrderRepository.Specifications.ifUCanSee(employee)).and(
                MarketOrderRepository.Specifications.systemServiceEqual(
                    systemServiceService.getCurrentSystemService(),
                ),
            ).and(MarketOrderRepository.Specifications.idEqual(id)).and(
                MarketOrderRepository.Specifications.submitDateTimeIsNull()
            )
        ) {
            it.one()
        }.orElse(null).orElse404()
        this.marketOrderRepository.delete(marketOrder)
        this.employeeOperateRecordService.deleteMarketOrder(marketOrder)
    }

    fun queryOrderCreatedEmployeesByMarketId(marketId: Int): List<IntIdAndName> {
        return this.employeeRepository.findAll(
            EmployeeRepository.Specifications.haveMarketsOrder(marketId).and(
                SystemServiceRepository.Specifications.systemServiceEquals(
                    { root -> root },
                    systemServiceService.getCurrentSystemService()
                )
            )
        ).map {
            IntIdAndName(it.id!!, it.name)
        }
    }

    @Transactional
    fun exportToExcel(id: Int, request: MarketOrderController.ExportToExcelRequest): InputStreamResource {
        val goodsList = this.marketOrderRepository.findByIdOrNull(id).orElse404().goodsList

        val workbook = exportGoodsDataToWorkbook(request.fields.map {
            GoodsExcelColumn.fromField(it)
        }.toTypedArray(),
            goodsList.map { goods ->
                goods.goods.excelRow.copy(amount = goods.amount, unit = goods.unit?.name)
            })
        return workbookToInputStreamResource(workbook)
    }

    @Transactional
    fun addItems(orderId: Int, goodsIds: List<Int>): List<MarketOrdersItemController.OrderItemInOrderSummary> {
        val currentSystemService = systemServiceService.getCurrentSystemService()
        val marketOrder = this.marketOrderRepository.findByIdAndMarket_SystemService(
            orderId,
            currentSystemService
        ).orElse404()
        val goodsList =
            goodsRepository.findByIdInAndSystemServiceAndDisableIsFalse(goodsIds, currentSystemService)
                .orElse404()
        return goodsList.map {
            orderItemInOrderSummary(marketOrder, it)
        }
    }

    @Transactional
    fun batchAddItems(
        orderId: Int,
        itemKeys: List<MarketOrdersItemController.AddOrderItemKey>
    ): List<MarketOrdersItemController.OrderItemInOrderSummary> {
        val currentSystemService = systemServiceService.getCurrentSystemService()
        val marketOrder = this.marketOrderRepository.findByIdAndMarket_SystemService(
            orderId,
            currentSystemService
        ).orElse404()
        val goodsList =
            goodsRepository.findByIdInAndSystemServiceAndDisableIsFalse(itemKeys.map { it.goodsId }, currentSystemService)
                .orElse404()
        return itemKeys.map { key ->
            val goods = goodsList.find { it.id == key.goodsId }.orElse404()
            orderItemInOrderSummary(marketOrder, goods, goods.subGoodsList.find { key.subGoodsId == it.id })
        }
    }


    @Transactional
    fun updateItemNote(goodsId: Int, orderId: Int, note: String) {
        val marketOrderItem =
            this.marketOrderItemRepository.findByMarketOrder_IdAndGoods_IdAndSubGoods_Id(orderId, goodsId, null)
                .orElse404()
        marketOrderItem.note = note
        this.marketOrderItemRepository.save(marketOrderItem)
        this.employeeOperateRecordService.updateMarketOrderItemNote(marketOrderItem)

    }

    @Transactional
    fun updateItemNote(goodsId: Int, orderId: Int, subGoodsId: Int, note: String) {
        val marketOrderItem =
            this.marketOrderItemRepository.findByMarketOrder_IdAndGoods_IdAndSubGoods_Id(orderId, goodsId, subGoodsId)
                .orElse404()
        marketOrderItem.note = note
        this.marketOrderItemRepository.save(marketOrderItem)
        this.employeeOperateRecordService.updateMarketOrderItemNote(marketOrderItem)
    }

    @Transactional(readOnly = true)
    fun queryLatestUncommitedMarketOrder(): List<MarketOrderController.LatestUncommitedMarketOrder> {
        val employee = employeeService.getRequiredCurrentEmployee()
        return this.marketOrderRepository.findAll(
            MarketOrderRepository.Specifications.marketSaleManagerEqual(employee.id!!)
                .or(MarketOrderRepository.Specifications.marketShoppingGuidesContains(employee.id!!))
                .or(MarketOrderRepository.Specifications.employeeEqual(employee.id)),
            PageRequest.of(0,2,Sort.by(Sort.Order.desc("createdDateTime")))
        ).content.map {
            MarketOrderController.LatestUncommitedMarketOrder(
                it.id,
                it.number,
                it.goodsList.size,
                it.createdDateTime,
                it.employee.toIntIdAndName(),
                it.market.toIntIdAndName(),
            )
        }
    }

    @Transactional
    fun importFromExcelItems(orderId:Int,items: List<MarketOrdersItemController.MarketOrderItemExcelItem>): Int {
        val marketOrder = this.marketOrderRepository.findByIdAndMarket_SystemService(
            orderId,
            systemServiceService.getCurrentSystemService()
        ).orElse404()

        val marketOrderItems = items.distinctBy { it.barcode + it.subGoodsNumber }
            .filterNot { item ->
                marketOrder.goodsList.any {
                    it.goods.barcode == item.barcode && it.subGoods?.number == item.subGoodsNumber
                }
            }.mapIndexedNotNull { index, item, ->
                MarketOrderItem().apply {
                    this.sequence = marketOrder.goodsList.nextSequence + index
                    val goods = goodsRepository.findByBarcodeAndSystemServiceAndDisableIsFalse(
                        item.barcode,
                        systemServiceService.getCurrentSystemService()
                    ).orElse404()
                    this.goods = goods
                    this.subGoods = if (item.subGoodsNumber == null)
                        null
                    else
                        goods.subGoodsList.find { subGoods -> subGoods.number == item.subGoodsNumber }?:return@mapIndexedNotNull null
                    this.amount = item.amount
                    this.unit = goods.units.find { it.name == item.unit }
                    this.note = goods.note
                    this.marketOrder = marketOrder
                }

            }
        this.marketOrderItemRepository.saveAll(marketOrderItems)
        return marketOrderItems.size
    }
}
